/*
 * Sistema Leilão de Câmbio - Módulo Web.
 *
 * Copyright (c) Banco Central do Brasil.
 *
 * Este software é confidencial e propriedade do Banco Central do Brasil.
 * Não é permitida sua distribuição ou divulgação do seu conteúdo sem
 * expressa autorização do Banco Central.
 * Este arquivo contém informações proprietárias.
 */
package br.gov.bcb.leilao.web.page.ranking;

import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import br.gov.bcb.leilao.web.enumeration.SortOrderEnum;

public class OrdenadorDeLista<T> {

    private String property;

    public void ordenar(List<T> listaParaOrdenar, String property, SortOrderEnum sortOrderEnum) {
        this.property = property;

        if (SortOrderEnum.ASCENDING.equals(sortOrderEnum)) {
            Collections.sort(listaParaOrdenar, new ComparadorAscedente());
        } else if (SortOrderEnum.DESCENDING.equals(sortOrderEnum)) {
            Collections.sort(listaParaOrdenar, new ComparadorDescendente());
        }
    }

    private class ComparadorAscedente implements Comparator<T> {

        @Override
        public int compare(T o1, T o2) {
            Object valor1 = obterValorRetornoProperty(o1, property);
            Object valor2 = obterValorRetornoProperty(o2, property);

            return compararObjetos(valor1, valor2);
        }
    }

    private class ComparadorDescendente implements Comparator<T> {

        @Override
        public int compare(T o1, T o2) {
            Object valor1 = obterValorRetornoProperty(o1, property);
            Object valor2 = obterValorRetornoProperty(o2, property);

            return compararObjetos(valor2, valor1);
        }
    }

    private Object obterValorRetornoProperty(T objeto, String property) {
        Object obj = objeto;
        try {
            String[] metodos = property.split("\\.");
            for (int i = 0; i < metodos.length; i++) {
                String getMetodo = prepararNomeMetodo(metodos[i]);
                obj = obj.getClass().getMethod(getMetodo).invoke(obj);
            }
        } catch (IllegalAccessException e) {
            e.toString();
        } catch (IllegalArgumentException e) {
            e.toString();
        } catch (SecurityException e) {
            e.toString();
        } catch (InvocationTargetException e) {
            e.toString();
        } catch (NoSuchMethodException e) {
            e.toString();
        }

        return obj;
    }

    private String prepararNomeMetodo(String nomeDoMetodo) {
        return "get" + upperCasePrimeiraLetra(nomeDoMetodo);
    }

    private String upperCasePrimeiraLetra(String string) {
        StringBuilder sb = new StringBuilder(string);
        sb.setCharAt(0, Character.toUpperCase(sb.charAt(0)));
        return sb.toString();
    }

    private static Integer compararObjetos(Object valor1, Object valor2) {
        Integer comparacao = 0;

        if (valor1 instanceof Integer) {
            comparacao = ((Integer) valor1).compareTo((Integer) valor2);
        }
        if (valor1 instanceof String) {
            comparacao = ((String) valor1).compareTo((String) valor2);
        }
        if (valor1 instanceof BigDecimal) {
            comparacao = ((BigDecimal) valor1).compareTo((BigDecimal) valor2);
        }

        return comparacao;
    }
}
